package com.csjbot.weedle_auto.serialport_util

import android_serialport_api.SerialPort
import com.csjbot.weedle_auto.SerialServer.util.bean.NetDataTypeTransform
import com.csjbot.weedle_auto.SerialServer.util.bean.SerialPortExceptionListener
import com.csjbot.weedle_auto.util.Csjlogger
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.security.InvalidParameterException
import java.util.*


class SerialPortUtil {
    private var mSerialPort: SerialPort? = null
    private var mOutputStream: OutputStream? = null
    private var mInputStream: InputStream? = null
    private var mReadThread: ReadThread? = null


    private inner class ReadThread : Thread("SerialPortUtil ReadThread") {
        override fun run() {
            super.run()
            while (!isInterrupted) {
                try {
                    var size: Int
                    val buffer = ByteArray(BUFFER_READ_SIZE)

                    if (mInputStream == null) {
                        Csjlogger.error("mInputStream == null")
                        return
                    }
                    size = mInputStream!!.read(buffer)
                    if (size > 0) {
//                        Csjlogger.info("UartConnectRK3288 {} read" + NetDataTypeTransform.dumpHex(buffer));
                        strickBuffer(buffer, size)
                    }
                } catch (e: IOException) {
                    return
                }

            }
        }
    }


    private val mBuffer = ByteArray(64)
    private var offset = 0
    private val CONTENT_WITHOUT_DATA = 6

    @Synchronized private fun strickBuffer(buf: ByteArray, size: Int) {
        //添加到缓冲区中
        System.arraycopy(buf, 0, mBuffer, offset, size)
        offset += size
        if (offset < mBuffer.size) {
            checkBuffer()
        } else {
            Arrays.fill(mBuffer, 0.toByte())
            offset = 0
        }
    }

    // TODO: 2017/6/2 这个在8.4寸安卓板上的串口需要更改。
    @Synchronized private fun checkBuffer() {
        // 6是最小的一个包
        if (mBuffer[0] == HEADER) {
            //            Csjlogger.info("收到上身板发送的原始数据 AA{}", NetDataTypeTransform.dumpHex(Arrays.copyOf(mBuffer, offset)));
            // 6是最小的一个包
            if (offset >= CONTENT_WITHOUT_DATA) {
                val len = mBuffer[4].toInt()
                if (len < 0) {
                    Arrays.fill(mBuffer, 0.toByte())
                    offset = 0
                    return
                }
                // 读到了一个完整的包
                if (offset == len + CONTENT_WITHOUT_DATA) {
//                    Csjlogger.info("收到上身板发送的原始数据 AA{}" + NetDataTypeTransform.dumpHex(Arrays.copyOf(mBuffer, offset)))
                    serialPortListener!!.onDataReceived(mBuffer, offset)
                    Arrays.fill(mBuffer, 0.toByte())
                    offset = 0
                }
            }
        } else if (mBuffer[0] == HEADER2) {
            Csjlogger.info("收到上身板发送的原始数据/**/ BB{}" + NetDataTypeTransform.dumpHex(Arrays.copyOf(mBuffer, offset)))
            if (offset < CONTENT_WITHOUT_DATA) return
            // 读到了一个完整的包
            if (offset == CONTENT_WITHOUT_DATA) {
                Csjlogger.info("收到上身板发送的原始数据 BB 16{}" + NetDataTypeTransform.dumpHex(Arrays.copyOf(mBuffer, offset)))
                Csjlogger.info("收到上身板发送的原始数据 BB 2{}" + NetDataTypeTransform.getBinaryStrFromByteArr(Arrays.copyOf(mBuffer, offset)))
                Csjlogger.info("收到上身板发送的原始数据 BB 10{}" + NetDataTypeTransform.bytesToInt(Arrays.copyOf(mBuffer, offset)))
                serialPortListener!!.onDataReceived(mBuffer, offset)
                Arrays.fill(mBuffer, 0.toByte())
                offset = 0
            }
        } else {
            // 如果头不是的话就舍弃，从头再来
            Arrays.fill(mBuffer, 0.toByte())
            offset = 0
        }
    }


    fun sendData(data: ByteArray) {
        if (mOutputStream != null) {
            try {
                mOutputStream!!.run {
                    write(data)
                    flush()
                }
            } catch (e: IOException) {
                e.printStackTrace()
            }
        } else {
            Csjlogger.error("mOutputStream is null")
        }
    }

//    @Throws(SecurityException::class, IOException::class, InvalidParameterException::class)
//    private fun getSerialPort(bt: Int, path: String): SerialPort {
//        if (mSerialPort == null) {
//            if (path.isEmpty() || bt == -1) {
//                throw InvalidParameterException()
//            }
//            val file = File(path)
//            mSerialPort = SerialPort(device = file, baudrate = bt, flags = 0)
//        }
//        return mSerialPort!!
//    }

    fun closeSerialPort() {
        if (mSerialPort != null) {
            mSerialPort!!.close()
            mSerialPort = null
        }
    }

    constructor()

    constructor(bt: Int, path: String, listener: SerialPortListener) {
        Csjlogger.debug("start SerialPortUtil")
        serialPortListener = listener
        try {
            if (mSerialPort == null) {
                if (path.isEmpty() || bt == -1) {
                    throw InvalidParameterException()
                }
                val file = File(path)
                mSerialPort = SerialPort(file, bt, 0)
            }
            mOutputStream = mSerialPort!!.outputStream//写入串口
            mInputStream = mSerialPort!!.inputStream//得到mSerialPort的输入流
            Csjlogger.debug("start SerialPortUtil")
            /* Create a receiving thread */
            mReadThread = ReadThread()
            mReadThread!!.start()//开启线程
        } catch (e: SecurityException) {
            exceptionListener!!.securityException(e)
            Csjlogger.error("You do not have read/write permission to the serial port")
        } catch (e: IOException) {
            exceptionListener!!.ioException(e)
            Csjlogger.error("The serial port can not be opened for an unknown   reason.")
        } catch (e: InvalidParameterException) {
            exceptionListener!!.invalidException(e)
            Csjlogger.error("Please configure your serial port first.")
        }
    }

    companion object {
        private var serialPortListener: SerialPortListener? = null
        private val HEADER = 0xAA.toByte()
        private val HEADER2 = 0xBB.toByte()
        private val BUFFER_READ_SIZE = 1
        private var exceptionListener: SerialPortExceptionListener? = null
        /**
         * 获取listener实例
         * 唯一实例
         */
        fun setSerialPortExceptionListener(listener: SerialPortExceptionListener) {
            exceptionListener = listener
        }
    }
}
